/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ResultEditor.AnnotationClasses.Mouse;

import ResultEditor.AnnotationClasses.Depot;
import ResultEditor.AnnotationClasses.ShowClassesInTreeView;
import ResultEditor.AnnotationClasses.Treeview_AnnotationNode;
import ResultEditor.AnnotationClasses.file_annotation;
import ResultEditor.Annotations.Annotation;
import java.awt.Color;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.border.BevelBorder;
import javax.swing.tree.TreePath;
import java.awt.event.ActionEvent;
import java.util.Vector;
import javax.swing.JSeparator;
import javax.swing.text.JTextComponent;
import javax.swing.tree.DefaultMutableTreeNode;


/**
 *
 * @author Chris
 */
public class ClickedListener {
    protected java.awt.event.MouseEvent evt;
    protected static JTree classTreeview;
    protected static UserInterface.GUI gui;
    private JPopupMenu popup;
    protected static JTextComponent comp;

    protected String selectedText = null;
    protected int selectedStart, selectedEnd;
    protected String classname;

    protected DeleteConfirm deletedialog;

    public ClickedListener(java.awt.event.MouseEvent evt, JTree classTreeview, UserInterface.GUI gui,
            JTextComponent comp){
        this.evt = evt;
        ClickedListener.classTreeview = classTreeview;
        ClickedListener.gui = gui;
        ClickedListener.comp = comp;
        this.selectedText = comp.getSelectedText();
        if ( this.selectedText != null ){
            this.selectedStart = comp.getSelectionStart();
            this.selectedEnd = comp.getSelectionEnd();
        }
    }

    private void setFlag_of_CreateAnnotation( java.awt.event.MouseEvent evt ){
        //if (evt.getClickCount() != 2)
        //    return;
        TreePath path = classTreeview.getPathForLocation(evt.getX(), evt.getY());
        if (path != null) {
            Object node = path.getLastPathComponent();
            //Object myobject = ((javax.swing.tree.DefaultMutableTreeNode)(node)).getUserObject();
            if (node == null)
                System.out.println("1008102259 - this selected node is not a markable node!!!");
            else{
                ResultEditor.AnnotationClasses.Treeview_ClassNode classnode = null;
                try{
                    classnode = (ResultEditor.AnnotationClasses.Treeview_ClassNode) node;
                    if (classnode == null){
                        System.out.println("1008102303 - error while convert \"object\" to \"classnode\"");
                        return;
                    }
                    boolean isAllow_toCreateAnnotation_asThisClass = classnode.isSelected_toCreateAnnotation();
                    classnode.setFlag_isSelected_toCreateAnnotation(!isAllow_toCreateAnnotation_asThisClass);
                    String markable_name =  classnode.getText();

                    setCurrentMarkable_toCreateNewAnnotation(markable_name, !isAllow_toCreateAnnotation_asThisClass );

                    // update GUI
                    // System.out.println("Current markable node = " + classnode.getText()
                    //              + " = " + classnode.isSelected_toCreateAnnotation() );
                    ((javax.swing.tree.DefaultMutableTreeNode)(node)).setUserObject( classnode );
                    classTreeview.updateUI();
                        
                } catch(Exception e) {
                    System.out.println("1008102300 - error while convert \"object\" to \"classnode\"");
                }
            }
        }
    }


    /**start processing this mouse clicked event*/
    public void process(){
        if ( evt == null )  return;
        if ( classTreeview == null )    return;
        //boolean debug = true;
        //if( debug == true)
        //    return;


        // clear any selected node highlight backgroup in treeview
        ShowClassesInTreeView scit = new ShowClassesInTreeView(classTreeview, gui);
        scit.removeAllNodehighlight();

        //System.out.println("x = " + evt.getX() + "; y = " + evt.getY() );
        
        // ##1## mouse right key pressed
        if( evt.getModifiers()== java.awt.event.InputEvent.BUTTON3_MASK ){

            TreePath path = classTreeview.getPathForLocation(evt.getX(), evt.getY());
            
            // ##1.1## process if user's click got some tree node
            if (path != null) {

                classTreeview.setSelectionPath(path);
                                
                Object node = path.getLastPathComponent();

                if( node == null )  return;

                
                // ##1.1.1## clicked class node in the tree view is class tree node
                if (node instanceof ResultEditor.AnnotationClasses.Treeview_ClassNode ){

                    setFlag_of_CreateAnnotation( evt );
                    //ResultEditor.AnnotationClasses.JClassCheckBox jc = (ResultEditor.AnnotationClasses.JClassCheckBox) ((javax.swing.tree.DefaultMutableTreeNode)(node)).getUserObject();
                    //if( jc != null ){

                    //    int xx = jc.getX();
                    //    System.out.println("jc x = " + xx);
                    //}else{System.out.println("not jc");}
                    // ##1.1.1.1## show all vaild position indicators
                    showAllValidPositionIndicator();

                    // ##1.1.1.2## if has text selected in the article, pop the popmenu
                    // to let user create a new annotation
                    //if( selectedText != null ) {
                    //    String selectedclassname = ((ResultEditor.AnnotationClasses.Treeview_ClassNode)node).getText().trim();
                    //    this.classname = selectedclassname;
                    //    popMemu( classname, evt );
                    //}

                    return;
                    //System.out.println(classname);
                } else if( !((javax.swing.tree.DefaultMutableTreeNode)node).isRoot() ) {
                // ##1.1.2## if node is annotation
                    String str = ((javax.swing.tree.TreeNode)node).toString();
                    str = getCleanAnnotationName( str );
                    //System.out.println("\n - annotation = ["+str+"]");
                    // only show position indicator to you just clicked annotation in current article

                    onlyShowValidPositionIndicator_for_DesignatedAnnotation( str );
                    
                    nnn(node, true);

                    return;

                }

            } else {
                // ##1.2## if no node got selected by user's mouse click
                showAllValidPositionIndicator();
                return;
            }
        }else{
            // ##2## left key or midkey pressed, not moust right key
            TreePath path = classTreeview.getPathForLocation(evt.getX(), evt.getY());

            // ##2.1## process if user's click got some tree node
            if (path != null) {

                classTreeview.setSelectionPath(path);

                Object node = path.getLastPathComponent();
                if( node == null )  return;


                // ##2.1.1## clicked class node in the tree view is class tree node
                if (node instanceof ResultEditor.AnnotationClasses.Treeview_ClassNode ){
                    /*Object o = classTreeview.findComponentAt(evt.getX(), evt.getY());
                    if ( o instanceof ResultEditor.AnnotationClasses.JClassCheckBox){
                        System.out.println("is class");
                    }else System.out.println(o.toString()+"not class");
                     * */
                    /*Object userObject = node.getUserObject();
                    if (userObject != null ){
                        ResultEditor.AnnotationClasses.JClassCheckBox thisclasscheckbox =
                               (ResultEditor.AnnotationClasses.JClassCheckBox) userObject;
                    }else{
                        System.out.println("1008101812 - user object get from current tree node is empty!!!");
                    }*/


                    //(((javax.swing.tree.DefaultMutableTreeNode)node)
                    /*int rowheight = classTreeview.getRowHeight(); // == 0, strange
                    int row =  classTreeview.getRowForLocation( evt.getX(), evt.getY() );
                    int xx = row*rowheight;
                    System.out.println("row = "+row+" ; rowheight = "+rowheight+"; select row x = " + xx);
                    */

                    // ##2.1.1.1## show all vaild position indicators
                    showAllValidPositionIndicator();

                } else if( !((javax.swing.tree.DefaultMutableTreeNode)node).isRoot() ) {
                    // ##2.1.2## if node is annotation
                    String str = ((javax.swing.tree.TreeNode)node).toString();
                    str = getCleanAnnotationName( str );
                    //System.out.println("\n - annotation = ["+str+"]");
                    // only show position indicator to you just clicked annotation in current article
                    onlyShowValidPositionIndicator_for_DesignatedAnnotation( str );

                    nnn(node, false);
                }

                return;

            } else {
            // ##2.2## if no node got selected by user's mouse click
            
                showAllValidPositionIndicator();

                return;
            }
        }
    }

    private void nnn(Object node, boolean is_right_button){
        
        if(( !is_right_button )&&(!gui.isShowAnnotations_toAllDoc()) )
            return;

        if(node instanceof Treeview_AnnotationNode) {
            Treeview_AnnotationNode annotationnode = (Treeview_AnnotationNode)node;
            if ( annotationnode != null ) {
                Vector<file_annotation> annotations = annotationnode.getAnnotations();
                if ( annotations != null ){

                    //for( file_annotation fa : annotations ){
                    //    System.out.println( fa.filename );
                    //}

                    if ( annotationnode.isNotAppeared_in_CurrentArticle )
                        popmenu_for_multipleDocument( annotationnode.getUniqueAnnotationText(), annotations, true );
                    else 
                        popmenu_for_multipleDocument( annotationnode.getUniqueAnnotationText(), annotations, false );
                }
            }
        }
    }

    private String getCleanAnnotationName(String text){
        if(( text == null )||(text.trim().length() < 1))
            return "";

        text = text.replaceAll("<html>", " ");
        text = text.replaceAll("<//html>", " ");
        text = text.replaceAll("<//b>", " ");
        text = text.replaceAll("<b>", " ");
        text = text.replaceAll("<font(.*)?>", " ");

        return text.trim();
    }

    private void showAllValidPositionIndicator(){
        gui.showValidPositionIndicators_setAll();
        gui.showValidPositionIndicators();
    }

    private int assignMeAUniqueIndex(){
         return ResultEditor.Annotations.AnnotationIndex.newAnnotationIndex();
    }

    private void ShowDialogToCreateAnnotation(String classname){
        //ShowAnnotationDlg ShowAnnotationDlg = new ShowAnnotationDlg( gui );
        //ShowAnnotationDlg.showDialog( gui.getX(), gui.getY(), gui.getWidth(), gui.getHeight(),
        //        this.selectedText, this.selectedStart, this.selectedEnd, classname);

        String testsourceFilename = ResultEditor.WorkSpace.WorkSet.getCurrentFile().getName().trim();

        ResultEditor.Annotations.Depot depot = new ResultEditor.Annotations.Depot();
        depot.articleInsurance( testsourceFilename );
        String createdate = commons.OS.getCurrentDate();
        String annotator_name = ResultEditor.Annotator.Manager.getAnnotatorName_OutputOnly();
        String annotator_id = ResultEditor.Annotator.Manager.getAnnotatorID_outputOnly();
        depot.addANewAnnotation( testsourceFilename,
                this.selectedText,
                this.selectedStart,
                this.selectedEnd,
                // creation date
                createdate,
                // annotation classname
                this.classname,
                annotator_name,
                annotator_id,
                null,
                null,
                assignMeAUniqueIndex()
                );

        ResultEditor.Annotations.Annotation annotation = new ResultEditor.Annotations.Annotation();
        annotation.annotationText = this.selectedText;
        annotation.spanstart = this.selectedStart;
        annotation.spanend = this.selectedEnd;
        annotation.creationDate = createdate;
        annotation.annotationclass = classname;
        annotation.annotator = "EHOST_Result_Editor";

        comp.setSelectionEnd(0);
        gui.showAnnotationCategoriesInTreeView_refresh();
        gui.repaintHighlighter();

        gui.showValidPositionIndicators();

        setSelectedDatainDepot( testsourceFilename, annotation );
        //gui.showAnnotationDetail(annotation);
        gui.showSelectedAnnotations_inList(0);

    }
    

    private void onlyShowValidPositionIndicator_for_DesignatedAnnotation( String annotation ){
        // ##1## only show indicator marks for annotations who have same annotation text
        gui.showValidPositionIndicators_setDesignated( annotation );
        gui.showValidPositionIndicators();
        
        // get filename of current text source
        String testsourceFilename = ResultEditor.WorkSpace.WorkSet.getCurrentFile().getName().trim();


        // ##2## selected annotation who have same annotation text in the list
        //ResultEditor.Annotations.Depot depot = new ResultEditor.Annotations.Depot();
        ResultEditor.Annotations.Depot.SelectedAnnotationSet
                .selectedAnnotations_byTheirText( testsourceFilename, annotation );
        
        //gui.showAnnotationDetail(annotation);
        gui.display_SetStatusInsiable_ToComparisionPanel();
        gui.showSelectedAnnotations_inList(0);

        gui.highlightAnnotations( annotation );
        
    }

    private void popMemu( String classname, java.awt.event.MouseEvent evt ){
        // popupDialog the popmenu
        popup = new JPopupMenu();
        popup = buildpopmenu(popup, "Create new annotation");
        //popup.setLabel("Justification");
        javax.swing.border.Border lines = new javax.swing.border.LineBorder(Color.black, 2);
        popup.setBorder( lines );

        popup.show( classTreeview, evt.getX(), evt.getY());

    }

    /**
     * To an annotation node in the treeview, if it not appear in current document,
     * show popmenu with "delete" and "navigator panel".
     * Otherwise, only show "delete" menu.
     */
    private void popmenu_for_multipleDocument(String annotationtext, Vector<file_annotation> file_annotations, boolean need_navigation_to_other_file
            ){
        popup = new JPopupMenu();
        popup = buildpopmenu(annotationtext, popup, file_annotations, need_navigation_to_other_file);
        javax.swing.border.Border lines = new javax.swing.border.LineBorder(Color.black, 2);
        popup.setBorder( lines );

        popup.show( classTreeview, evt.getX(), evt.getY());
    }


    private JPopupMenu buildpopmenu(final String annotationtext, final JPopupMenu popup, final Vector<file_annotation> file_annotations,
            final boolean need_navigation_to_other_file ){
        if (( file_annotations == null )&&( file_annotations.size() < 1 ))
            return popup;

        final File_Annotations_Depot depot = new File_Annotations_Depot();
        depot.clear();

        for( file_annotation fa : file_annotations ){
            depot.add(fa);            
        }

        if ((need_navigation_to_other_file)&&( depot.file_annotations != null )){
            for( final File_ANNOTATIONS faa : depot.file_annotations ) {
                
                final ActionListener menuListener = new ActionListener() {
                    public void actionPerformed(ActionEvent event) {
                        ClickedListener.this.jumpToDesignated_fileAndAnnotations( faa.Filename, faa.annotations);
                    }
                };


                JMenuItem item;
                item = new JMenuItem( "in \""+ faa.Filename + "\"("+faa.annotations.size()+")"  , new ImageIcon("1.gif"));
                item.setHorizontalTextPosition(JMenuItem.RIGHT);
                item.addActionListener(menuListener);
                popup.add(item);
            }

            JSeparator seperator = new JSeparator();
            popup.add(seperator);
        }

        

        JMenuItem deleteitem = new JMenuItem( "delete"  , new ImageIcon("1.gif"));
        final ActionListener deletemenuListener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                ClickedListener.this.showDialog_delelteUniqueTypeAnnotation( annotationtext, need_navigation_to_other_file );
            }
        };
        deleteitem.addActionListener(deletemenuListener);
        popup.add(deleteitem);

        popup.setLabel("J");
        popup.setBorder(new BevelBorder(BevelBorder.RAISED));
        return popup;
    }

    private void showDialog_delelteUniqueTypeAnnotation(String annotationtext, boolean is_appeared_in_current_doc){
        if ( annotationtext == null )
            return;

        if (this.deletedialog != null)
            deletedialog.dispose();

        deletedialog = new DeleteConfirm(gui, annotationtext, is_appeared_in_current_doc);
        deletedialog.setVisible(true);



    }

    private void jumpToDesignated_fileAndAnnotations(String filename,
            final Vector<Annotation> annotations){

        // System.out.println("annotationtext=["+ annotationtext+"");
        // ##1## open disignated text source by filename
        gui.goUserDesignated( filename );

        String annotationtext = annotations.get(0).annotationText;


        

        
        ResultEditor.Annotations.Depot.SelectedAnnotationSet.
                selectedAnnotations_byTheirText( filename, annotationtext );

        gui.display_SetStatusInsiable_ToComparisionPanel();
        gui.showSelectedAnnotations_inList(0);
        

        // set focus and highlight first selected annotations
        gui.setFocusOn( annotations.get(0).spanstart );
        gui.hilightPhrase( annotations.get(0));

        gui.showValidPositionIndicators_setDesignated( annotationtext );
        gui.showValidPositionIndicators();
    }


    private JPopupMenu buildpopmenu(final JPopupMenu popup, final String annotationClassname){
        final ActionListener menuListener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
               ShowDialogToCreateAnnotation( annotationClassname );
            }
        };


        JMenuItem item;
        popup.add(item = new JMenuItem(annotationClassname, new ImageIcon("1.gif")));
        item.setHorizontalTextPosition(JMenuItem.RIGHT);
        item.addActionListener(menuListener);
        
        popup.setLabel("Justification");
        popup.setBorder(new BevelBorder(BevelBorder.RAISED));
        return popup;
    }

    

    private void setSelectedDatainDepot( String filename, ResultEditor.Annotations.Annotation annotation ){
         int index = getAnnotationIndex( filename, annotation);
         if ( index < 0)
             return;

         ResultEditor.Annotations.Depot depot = new ResultEditor.Annotations.Depot();
         depot.setSelectedAnnotationsIndexes(index);
     }


    private int getAnnotationIndex(String filename, ResultEditor.Annotations.Annotation annotation){
        if ( annotation == null )
            return -1;
        if ( filename == null  )
            return -1;

        ResultEditor.Annotations.Depot depot = new ResultEditor.Annotations.Depot();
        ResultEditor.Annotations.Article article = depot.getArticleByFilename(filename.trim());
        if ( article == null )
            return -1;

        if ( article.annotations == null )
            return -1;

        int size = article.annotations.size();
        for(int i=0;i<size;i++){
            ResultEditor.Annotations.Annotation thisannotation = article.annotations.get(i);
            if ( thisannotation == null )
                continue;

            if ( thisannotation.annotationText.trim().compareTo( annotation.annotationText.trim()) == 0 )
                if( thisannotation.spanstart == annotation.spanstart )
                    if( thisannotation.spanend == annotation.spanend )
                        if( thisannotation.creationDate.trim().compareTo( annotation.creationDate.trim() ) == 0 )
                            if( thisannotation.annotator.trim().compareTo( annotation.annotator.trim() ) == 0)
                                if( annotation.annotationclass.trim().compareTo( annotation.annotationclass.trim() ) == 0 )
                                    return i;


        }

        return -1;
    }

    /**
     * While you just enabled a markable as current markable type for creation
     * of new annotation, only this markable could be indicated by crossed lines
     * in its colorful markable category bar. If no markable was set, all markables
     * should be
     */
    private void setCurrentMarkable_toCreateNewAnnotation(String markablename, boolean isSelected){
        if ( classTreeview == null ){
            System.out.println("1008110000 - could not found class tree view while try to set status to markables.");
            return;
        }
        if ( markablename == null) {
            setCurrentMarkable_inParametersSpace( null );
        }

        if ( markablename.trim().length() < 1 ) {
            System.out.println("1008110019 - could not found valid markable name while try to set status to markables.");
            return;
        }


        if( isSelected )
            setCurrentMarkable_inParametersSpace( markablename.trim() );
        else setCurrentMarkable_inParametersSpace( null );

        DefaultMutableTreeNode  root = (DefaultMutableTreeNode ) classTreeview.getModel().getRoot();
        if ( root == null )
            return;

        int amount_of_markables = root.getChildCount();
        for( int i=0; i< amount_of_markables; i++){
            Object object = root.getChildAt(i);
            if ( object instanceof ResultEditor.AnnotationClasses.Treeview_ClassNode ){
                ResultEditor.AnnotationClasses.Treeview_ClassNode classnode = (ResultEditor.AnnotationClasses.Treeview_ClassNode)object;
                if( classnode.getText().trim().compareTo(markablename.trim())==0 ){
                    continue;
                }
                classnode.setFlag_isSelected_toCreateAnnotation(false);
                ((javax.swing.tree.DefaultMutableTreeNode)object).setUserObject( classnode );
            }
        }
    }

    private void setCurrentMarkable_inParametersSpace( String markableName ){
        env.Parameters.currentMarkables_to_createAnnotation_by1Click = markableName;
    }



}
class File_ANNOTATIONS{
    String Filename;
    Vector<Annotation> annotations = new Vector<Annotation>();
}

class File_Annotations_Depot{
    Vector<File_ANNOTATIONS> file_annotations = new Vector<File_ANNOTATIONS>();

    public void clear(){
        file_annotations.clear();
    }

    public void add(file_annotation fa){
        if ( fa == null )
            return;

        if ( existed(fa) ) {
            addAnnotation_toExistedFile( fa );
        }else{
            File_ANNOTATIONS faa = new File_ANNOTATIONS();
            faa.Filename = fa.filename;
            faa.annotations.add( fa.annotation );
            file_annotations.add(faa);
        }
    }

    private void addAnnotation_toExistedFile( file_annotation fa ){
        if ( file_annotations == null ) {
            return;
        }

        for( File_ANNOTATIONS faa : file_annotations ){
            if ( faa == null )
                continue;

            if ( faa.Filename.equals(fa.filename) ){
                faa.annotations.add( fa.annotation );
            }
        }
    }

    public boolean existed( file_annotation fa ){
        if ( file_annotations == null ) {
            file_annotations = new Vector<File_ANNOTATIONS>();
            return false;
        }

        for( File_ANNOTATIONS faa : file_annotations ){
            if ( faa == null )
                continue;

            if ( faa.Filename.equals(fa.filename) )
                return true;
        }

        return false;
    }
}